package tools.maf;

import java.util.Formatter;
import java.util.Locale;

import tools.Alignment;
import tools.overlap.overlapMethods;

public class mafAlignment implements Alignment{

	private int score;
	private String mismap;
	private mafSequence target,query;
	boolean hasTarget,hasQuery;
	
	public mafAlignment(){
		super();
		hasTarget=false;
		hasQuery=false;
		target= new mafSequence();
		query= new mafSequence();
	}
	
	public mafAlignment(String aLine){
		this();
		String[] l= aLine.split("[ =]");
		score=Integer.parseInt(l[2]);
		mismap= l[4];
	}
	
	public mafAlignment(mafAlignment b){
		this.score=b.score;
		this.mismap=b.mismap;
		this.target= new mafSequence(b.target);
		this.query= new mafSequence(b.query);
		this.hasTarget=b.hasTarget;
		this.hasQuery=b.hasQuery;
	}
	
	public void addTargetSline(String sLine){
		target.addSequenceLine(sLine);
		hasTarget=true;
	}
	
	public void addTargetQline(String qLine){
		target.addQualityLine(qLine);
	}
	
	public void addQuerySline(String sLine){
		query.addSequenceLine(sLine);
		hasQuery=true;
	}
	
	public void addQueryQline(String qLine){
		query.addQualityLine(qLine);
	}
	
	
	
	public void trimTargetLeft(int size) throws Exception{
		int trim=0;
		for(int i=0;i<size;){
			if(query.trimLeft()==-1){
				System.err.println("Overtrimming query sequence from left: "+ this.getQname());
			}
			trim=target.trimLeft();
			if(trim==-1){
				System.err.println("Overtrimming target sequence from left"+ this.getQname());
			}else{
				i+=trim;
			}
		}
		while(query.gapLeft() || target.gapLeft()){ // what about inserts????
			if(query.trimLeft()==-1){
				System.err.println("Overtrimming gaps in query sequence from left: "+ this.getQname());
			}
			if(target.trimLeft()==-1){
				System.err.println("Overtrimming gaps in target sequence from left"+ this.getQname());
			}
		}
	}
	
	public void trimTargetRight(int size)throws Exception{
		int trim=0;
		for(int i=0;i<size;){
			if(query.trimRight()==-1){
				System.err.println("Overtrimming query sequence from right: "+ this.getQname());
			}
			trim=target.trimRight();
			if(trim==-1){
				System.err.println("Overtrimming target sequence from right"+ this.getQname());
			}else{
				i+=trim;
			}
		}
		while(query.gapRight() || target.gapRight()){ // what about inserts????
			if(query.trimRight()==-1){
				System.err.println("Overtrimming gaps in query sequence from right: "+ this.getQname());
			}
			if(target.trimRight()==-1){
				System.err.println("Overtrimming gaps in target sequence from right"+ this.getQname());
			}
		}
	}
	
	public String toString(){
		StringBuilder sb= new StringBuilder();
		Formatter formatter= new Formatter(sb, Locale.US);
		formatter.format("a score=%s mismap=%s", score,mismap);
		StringBuffer format=new StringBuffer(" %-");
		if(target.getName().length()>query.getName().length()){
			format.append(target.getName().length());
		}else{
			format.append(query.getName().length());
		}
		format.append("s%");
		if(target.getStart()>query.getStart()){
			format.append((target.getStart()+" ").length());
		}else{
			format.append((query.getStart()+" ").length());
		}
		format.append("s%");
		if(target.getAlignmentLength()>query.getAlignmentLength()){
			format.append((target.getAlignmentLength()+" ").length());
		}else{
			format.append((query.getAlignmentLength()+" ").length());
		}
		format.append("s %1s%");
		if(target.getTotLength()>query.getTotLength()){
			format.append((target.getTotLength()+" ").length());
		}else{
			format.append((query.getTotLength()+" ").length());
		}
		format.append("s %s");
		formatter.format("\ns"+format.toString(), target.getName(), target.getStart(), target.getAlignmentLength(), target.getStrand(), target.getTotLength(), target.getSequence());
		if(target.hasQuality()){
			formatter.format("\nq"+format.toString(), target.getName(),"", "", "", "", target.getQuality());
		}
		formatter.format("\ns"+format.toString(), query.getName(), query.getStart(), query.getAlignmentLength(), query.getStrand(), query.getTotLength(), query.getSequence());
		if(query.hasQuality()){
			formatter.format("\nq"+format.toString(), query.getName(),"", "", "", "", query.getQuality());
		}
		formatter.close();
		return sb.toString()+"\n";
	}
	
	
	@Override
	public char getStrand() {
		return query.getStrand();
	}

	@Override
	public String getTname() {
		return target.getName();
	}

	@Override
	public String getQname() {
		return query.getName();
	}

	@Override
	public int getTstart() {
		return target.getStart();
	}

	@Override
	public int getTend() {
		return target.getStart()+target.getAlignmentLength();
	}

	@Override
	public int getType() {
		return 3;
	}
	
	public int getAlignmentLength(){
		return target.getAlignmentLength();
	}

	@Override
	public boolean overlaps(Alignment b) throws Exception {
		return overlapMethods.mafOverlap(this, b,true);
	}
	
	public boolean overlapsNoStrand(mafAlignment b) throws Exception{
		if(!this.getTname().equals(b.getTname())){
			return false;
		}
		final int astart=this.getTstart(),aend=this.getTend(),bstart=b.getTstart(),bend=b.getTend();
		if((astart>=bstart&&astart<bend)||(bstart>=astart&&bstart<aend)){
			return true;
		}
		return false;
	}

}
